package main

import (
	"runtime"
	"time"
)

/*
channel 是通道 	done := make(chan struct{}) 没有设置容量是同步阻塞，done := make(chan struct{}，1) 是异步，只有管道满了才会阻塞 是FIFO类型的
*/
func main() {
	//println(data)
	// TestChannel() // 测试同步阻塞
	// TestChannel1() // 测试异步写入
	//TestChannel2() // 异步去读空的有容量的channel： 读的会先【阻塞】 然后等到【写入的结束】时候就【读出消息】 最后一个 协程读的读不到就一直等待最后 【死锁】
	//TestChannel3() // 读操作之前关闭chan 但是先写入协程在前面
	//TestChannel3a()
	// 1. 当使用协程去写入的时候 【panic: send on closed channel】&& ok == false --- 读数据之后才会panic
	// 2.不用协程去写可以读到消息 虽然 close(done) time.sleep() 但是 第一个始终都可以读到剩余的消息，v == true, 但是之后 读出来是类型的默认值 并且 v == false
	//TestChannel4() // 写一个关闭的协程[有cap] 直接panic 【panic: send on closed channel】
	//TestChannel5() // 写入一个nil chan  [chan send (nil chan)]  /  读一个 nil chan  [chan receive (nil chan)]:
	//TestChannel6() // 读一个关闭的chan 【没有cap】 没有错误，程序顺序执行 读出来的是默认值，ok==false  写入 panic: send on closed channel
	//TestChannel3a()
}
func TestChannel() {
	done := make(chan struct{})
	go func() {
		done <- struct{}{} // 尝试去写
		println("----write----")
	}()
	go func() {
		time.Sleep(10 * time.Second)
		<-done // 读
		println("----read----")
	}()
	select {}
}
func TestChannel1() {
	done := make(chan struct{}, 1)
	go func() {
		done <- struct{}{} // 尝试去写
		println("----write----")
	}()
	go func() {
		time.Sleep(10 * time.Second)
		<-done // 读
		println("----read----")
	}()
	select {}
}
func TestChannel2() {
	done := make(chan struct{}, 2)
	go func() {
		_, ok := <-done // 读
		println("----read----", ok)
	}()
	go func() {
		done <- struct{}{} // 尝试去写
		println("----write----")
	}()
	go func() {
		time.Sleep(10 * time.Second)
		_, ok := <-done // 读
		println("----read----", ok)
	}()
	select {}
}
func TestChannel3() {
	done := make(chan bool, 2)
	done <- true // 尝试去写
	println("----write----")
	//go func() {
	//	done <- "test channel" // 尝试去写
	//	println("----write----")
	//}()
	go func() {
		close(done)
		time.Sleep(1 * time.Second)
		v, ok := <-done // 读1
		println(v, " -【1】---read---- ", ok)
		v, ok = <-done // 读2
		println(v, " -【2】---read---- ", ok)
		v, ok = <-done // 读3
		println(v, " -【3】---read---- ", ok)
	}()
	select {}
}
func TestChannel3a() {
	runtime.GOMAXPROCS(1)
	done := make(chan bool, 1)
	go func() {
		println("----head----")
		done <- true // 尝试去写
		println("----write----")
	}()
	go func() {
		close(done)
		v, ok := <-done // 读1
		println(v, " -【1】---read---- ", ok)
	}()
	select {}
}
func TestChannel4() {
	done := make(chan bool, 2)
	go func() {
		close(done)
		done <- true
	}()
	select {}
}
func TestChannel5() {
	var done chan struct{}
	<-done
}
func TestChannel6() {
	done := make(chan bool)
	println("--close front-")
	close(done)
	println("--write front-")
	v, ok := <-done
	println(v, " ---end--- ", ok)
	time.Sleep(2 * time.Second)
}

//----write----
//test channel  -【1】---read----  true
//  -【2】---read----  false
//  -【3】---read----  false
